home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / utils / zoom.zoo / zoomacc.c < prev    next >
C/C++ Source or Header  |  1991-04-07  |  8KB  |  369 lines

  1. /*
  2.  * Zoom accessory
  3.  *
  4.  */
  5.  
  6. #include <osbind.h>
  7. #include <linea.h>
  8. #include <aes.h>
  9. #include <vdi.h>
  10.  
  11. #define elements(p) (p).g_x, (p).g_y, (p).g_w, (p).g_h
  12. #define pointers(p) &(p).g_x, &(p).g_y, &(p).g_w, &(p).g_h
  13.  
  14. #define clip(lower, val, upper) min((upper), max((lower), (val)))
  15.  
  16. #define WF_PARTS (NAME+CLOSE+MOVE)
  17.  
  18. typedef unsigned char    uchar;
  19. typedef unsigned short    ushort;
  20. typedef unsigned long    ulong;
  21.  
  22. #ifdef LATTICE
  23. extern long _STACK = 2048;
  24. #endif
  25.  
  26. /*
  27.  * Assembler functions to zoom up a single screen line and to blit the zoomed
  28.  * buffer onto the screen *fast*
  29.  *
  30.  */
  31. extern void zoomLine(void *, void *, short, short);
  32. extern void qblit(void *, void *, short);
  33.  
  34. #ifdef ACCorPRG
  35. extern int _XMODE;            /* Lattice startup stub variable: 2 = DA */
  36. #endif
  37.  
  38. short handle;                /* VDI handle */
  39. short m[8];                    /* AES message buffer */
  40. short err;                    /* Accessory installed? */
  41. uchar zoomed[128][16];        /* Array of zoomed pixels */
  42. struct la_data *data;        /* Line A data */
  43. uchar *display;                /* Pointer to screen memory */
  44. char   *title = "  Zoom ";    /* The DA title as well as the window title */
  45. MFDB  zoomarea = {zoomed, 128, 128, 8, 0, 1, 0, 0, 0};
  46. MFDB  screen;
  47.  
  48. /*
  49.  * Function:    Convert a window work area so that it lies on a word boundary
  50.  *
  51.  * Parameters:    Original work area, result work area
  52.  *
  53.  * Returns:        None
  54.  *
  55.  */
  56. void
  57. work2work(GRECT *work1, GRECT *work2)
  58. {
  59.     work2->g_x = (work1->g_x + 15) / 16;
  60.     work2->g_x = work2->g_x * 16 - 1;
  61.     work2->g_y = work1->g_y;
  62.     work2->g_w = work1->g_w;
  63.     work2->g_h = work1->g_h;
  64. }
  65.  
  66. /*
  67.  * Function:    Convert a window border to a word-aligned work area
  68.  *
  69.  * Parameters:    Border area, result work area
  70.  *
  71.  * Returns:        None
  72.  *
  73.  */
  74. void
  75. curr2work(GRECT *curr, GRECT *work)
  76. {
  77.     GRECT temp;
  78.  
  79.     wind_calc(WC_WORK, WF_PARTS, elements(*curr), pointers(temp));
  80.     work2work(&temp, work);
  81. }
  82.  
  83. /*
  84.  * Function:    Convert a window border area so that it lies on screen and has
  85.  *                a word-aligned work area
  86.  *
  87.  * Parameters:    Original border area, result border area
  88.  *
  89.  * Returns:        None
  90.  *
  91.  */
  92. void
  93. curr2curr(GRECT *curr1, GRECT *curr2)
  94. {
  95.     GRECT temp;
  96.  
  97.     wind_get(0, WF_WORKXYWH, pointers(temp));
  98.     curr1->g_x = min(curr1->g_x, temp.g_x + temp.g_w - curr1->g_w - 2);
  99.     curr1->g_y = min(curr1->g_y, temp.g_y + temp.g_h - curr1->g_h - 2);
  100.     curr2work(curr1, &temp);
  101.     wind_calc(WC_BORDER, WF_PARTS, elements(temp), pointers(*curr2));
  102. }
  103.  
  104. /*
  105.  * Function:    Produce a zoomed display in the global zoomed array (assuming
  106.  *                a THIN_CROSS mouse, the area is offset by the hot-spot of 7,7)
  107.  *
  108.  * Parameters:    Mouse x and y coordinates of top-left corner of area
  109.  *
  110.  * Returns:        None
  111.  *
  112.  */
  113. void
  114. zoom(short x, short y)
  115. {
  116.     uchar *scr;
  117.  
  118.     x = clip(0, x - 7, data->ld_vwrap * 8 - 16);
  119.     y = clip(0, y - 7, V_Y_MAX - 16);
  120.     scr = display + 2 * (x / 16);
  121.     scr += (long)y * data->ld_vwrap;
  122.     graf_mouse(M_OFF, NULL);
  123.     zoomLine(scr, zoomed, data->ld_vwrap, x % 16);
  124.     graf_mouse(M_ON, NULL);
  125. }
  126.  
  127. /*
  128.  * Function:    Function called by wind_redraw to redraw the window from the
  129.  *                zoomed buffer.  Also, a white pixel border is drawn on 2 sides
  130.  *
  131.  * Parameters:    Window handle, area to redraw
  132.  *
  133.  * Returns:        1 (continue redrawing)
  134.  *
  135.  */
  136. int
  137. redraw(int win, GRECT *p)
  138. {
  139.     GRECT work;
  140.     short pxy[8];
  141.  
  142.     pxy[0] = p->g_x; pxy[1] = p->g_y;
  143.     pxy[2] = p->g_x + p->g_w - 1;
  144.     pxy[3] = p->g_y + p->g_h - 1;
  145.     vs_clip(handle, 1, pxy);
  146.  
  147.     wind_get(win, WF_WORKXYWH, pointers(work));
  148.     pxy[0] = work.g_x + work.g_w - 1;
  149.     pxy[1] = work.g_y;
  150.  
  151.     pxy[2] = work.g_x;
  152.     pxy[3] = work.g_y;
  153.  
  154.     pxy[4] = work.g_x;
  155.     pxy[5] = work.g_y + work.g_h - 1;
  156.  
  157.     vsl_color(handle, WHITE);
  158.     v_pline(handle, 3, pxy);    /* Draw a pixel border on the top & left */
  159.     vs_clip(handle, 0, pxy);
  160.  
  161.     work.g_x++; work.g_y++;
  162.     work.g_w--; work.g_h--;
  163.     rc_intersect(&work, p);
  164.  
  165.     pxy[0] = p->g_x - work.g_x; pxy[1] = p->g_y - work.g_y;
  166.     pxy[2] = pxy[0] + p->g_w - 1; pxy[3] = pxy[1] + p->g_h - 1;
  167.  
  168.     pxy[4] = p->g_x; pxy[5] = p->g_y;
  169.     pxy[6] = p->g_x + p->g_w - 1; pxy[7] = p->g_y + p->g_h - 1;
  170.     vro_cpyfm(handle, S_ONLY, pxy, &zoomarea, &screen);
  171.     return 1;
  172. }
  173.  
  174. #ifndef LATTICE
  175. /*
  176.  * Function:    Manage window redraws by calling a supplied function for
  177.  *            each valid screen rectangle
  178.  *            From the Lattice C Atari Library Manual pp73-74
  179.  *
  180.  * Parameters:    Window handle, redraw area, redrawing function
  181.  *
  182.  * Returns:        1 if OK, 0 otherwise
  183.  *
  184.  */
  185. int
  186. wind_redraw(int win, GRECT *area, int (*redraw)(int, GRECT *))
  187. {
  188.     GRECT box;
  189.     int   ok = 1;
  190.  
  191.     graf_mouse(M_OFF, NULL);
  192.     wind_update(BEG_UPDATE);
  193.     wind_get(win, WF_FIRSTXYWH, pointers(box));
  194.     while (box.g_w && box.g_h) {
  195.         if (rc_intersect(area, &box))
  196.             if (!(ok = redraw(win, &box)))
  197.                 break;
  198.         wind_get(win, WF_NEXTXYWH, pointers(box));
  199.     }
  200.     wind_update(END_UPDATE);
  201.     graf_mouse(M_ON, NULL);
  202.     return ok;
  203. }
  204. #endif
  205.  
  206. /*
  207.  * Function:    Handle the opened zoom window
  208.  *
  209.  * Parameters:    None
  210.  *
  211.  * Returns:        None
  212.  *
  213.  */
  214. void
  215. doZoom(void)
  216. {
  217.     GRECT work = {127, 127, 129, 129};
  218.     GRECT curr;
  219.     uchar *scr;
  220.     short win;
  221.     short x, y, junk;
  222.     short ev;
  223.     short top;
  224.     int   done = 0;
  225.  
  226.     wind_calc(WC_BORDER, WF_PARTS, elements(work), pointers(curr));
  227.     win = wind_create(WF_PARTS, elements(curr));
  228.     if (win < 0)
  229.         return;
  230.     wind_title(win, title + 1);
  231.     wind_open(win, elements(curr));
  232.     graf_mkstate(&x, &y, &junk, &junk);
  233.     zoom(x, y);
  234.     graf_mouse(THIN_CROSS, NULL);
  235.  
  236.     do {
  237.         ev = evnt_multi(MU_M1 | MU_MESAG,
  238.             0, 0, 0,
  239.             1, x, y, 1, 1,
  240.             0, 0, 0, 0, 0,
  241.             m,
  242.             0, 0,
  243.             &x, &y,
  244.             &junk, &junk, &junk, &junk);
  245.  
  246.         wind_update(BEG_UPDATE);
  247.  
  248.         wind_get(win, WF_TOP, &top, &junk, &junk, &junk);
  249. /*
  250.  * It IS possible to get MU_M1 events if the window is NOT topped!!
  251.  *
  252.  */
  253.         if (top == win && (ev & MU_M1)) {
  254.             zoom(x, y);
  255.             scr = display + (work.g_x + 1) / 8;
  256.             scr += (long)(work.g_y + 1) * data->ld_vwrap;
  257.             graf_mouse(M_OFF, NULL);
  258.             qblit(scr, zoomed, data->ld_vwrap);
  259.             graf_mouse(M_ON, NULL);
  260.         }
  261.  
  262.         if (ev & MU_MESAG)
  263.             switch (m[0]) {
  264.             case WM_CLOSED:
  265.                 wind_close(win);
  266.                 wind_delete(win);    /* Fall through */
  267.             case AC_CLOSE:
  268.                 done = 1;
  269.                 break;
  270.             case AC_OPEN:
  271.                 wind_set(win, WF_TOP);
  272.                 break;
  273.             case WM_TOPPED:
  274.                 if (m[3] == win) {
  275.                     wind_set(win, WF_TOP);
  276.                     graf_mouse(THIN_CROSS, NULL);
  277.                 }
  278.                 break;
  279.             case WM_REDRAW:
  280.                 wind_redraw(win, (GRECT *)&m[4], redraw);
  281.                 break;
  282.             case WM_MOVED:
  283.                 curr2curr((GRECT *)&m[4], &curr);
  284.                 wind_set(win, WF_CURRXYWH, elements(curr));
  285.                 wind_get(win, WF_WORKXYWH, pointers(work));
  286.                 break;
  287.             default:
  288.                 break;
  289.             }
  290.  
  291.         wind_update(END_UPDATE);
  292.  
  293.     } while (!done);
  294.     graf_mouse(ARROW, NULL);
  295. }
  296.  
  297. /*
  298.  * Function:    Initialise GEM, install as a DA, get screen address.
  299.  *
  300.  * Parameters:    None
  301.  *
  302.  * Returns:        None (sets err global)
  303.  *
  304.  */
  305. void
  306. init(void)
  307. {
  308.     short workin[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2};
  309.     short workout[57];
  310.     short junk;
  311.     short id;
  312.  
  313.     err = 0;
  314.     data = linea0();
  315.     if (data->ld_vplanes != 1)
  316.         err = -1;
  317.  
  318.     display = (uchar *)Logbase();
  319.  
  320.     id = appl_init();
  321. #ifdef ACCorPRG
  322.     if (_XMODE == 2)
  323. #endif
  324.  
  325.         err = menu_register(id, title);
  326. #ifdef ACCorPRG
  327.     else
  328.         err = 0;
  329. #endif
  330.  
  331.     screen.fd_addr = NULL;
  332.     handle = graf_handle(&junk, &junk, &junk, &junk);
  333.     v_opnvwk(workin, &handle, workout);
  334. }
  335.  
  336. /*
  337.  * Function:    Main program
  338.  *
  339.  * Parameters:    None
  340.  *
  341.  * Returns:        None (never returns if run as an accessory)
  342.  *
  343.  */
  344. void
  345. main(void)
  346. {
  347.     init();
  348.  
  349. #ifdef ACCorPRG
  350.     if (_XMODE == 2) {
  351. #endif
  352.         if (err == -1)
  353.             Cconws("Error installing \033pZoomAcc\033q!\r\n");
  354.         for (;;) {
  355.             evnt_mesag(m);
  356.             if (err != -1 && m[0] == AC_OPEN)
  357.                 doZoom();
  358.         }
  359. #ifdef ACCorPRG
  360.     } else {
  361.         doZoom();
  362.         v_clsvwk(handle);
  363.         appl_exit();
  364.     }
  365. #endif
  366. }
  367.  
  368. /* End of zoomacc.c */
  369.